#include "HAPI_lib.h"
#include "Visualisation.h"
#include "WorldModel.h"
#include "ProjectileManager.h"
#include "ExplosionManager.h"
#include "EnemyManager.h"
#include "AI.h"
#include "UserInterface.h"
#include "Sound.h"
#include "EntityBoss.h"

#include <tinyxml.h>
void HAPI_Main()
{
	//open the xml file
	TiXmlDocument gameData("./data/xmlFile/gameData.xml");
	if(!gameData.LoadFile()){
		HAPI->UserMessage("ERROR: cannot open the xml file","ERROR");
		return;
	}
	TiXmlHandle handle(&gameData);

	//initialisation of the visualisation component

	//get the width of the screen
	int screenWidth;
	int screenHeight;
	TiXmlElement *xmlElement = handle.FirstChildElement().FirstChildElement().FirstChildElement().Element();
	if(!xmlElement)return;
	string temp=xmlElement->GetText();
	screenWidth=atoi(temp.c_str());

	//get the height of the screen
	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement)return;
	temp=xmlElement->GetText();
	screenHeight=atoi(temp.c_str());

	HAPI_UserResponse fullScreen;
	HAPI->UserMessage("Do you wish to play in full screen?","FULL SCREEN",eButtonTypeYesNo,&fullScreen);
	if(fullScreen==eUserResponseYes)
	{
		if(!HAPI->Initialise(&screenWidth, &screenHeight,HAPI_INIT_FULLSCREEN))
		{
			return;
		}
	}
	else
	{
		if(!HAPI->Initialise(&screenWidth, &screenHeight))
		{
			return;
		}
	}	
	VIS.setScreenWidth(screenWidth);
	VIS.setScreenHeight(screenHeight);
	VIS.setScreen(HAPI->GetScreenPointer());


	//loading of the sprites
	bool errorLoadingTexture=false;
	
	xmlElement=handle.FirstChildElement().Child(1).FirstChildElement().Element();
	if(!xmlElement) return;
	int indexSMap1 = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSMap1,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSMap2 = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSMap2,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSDragon = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSDragon,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSCloud1 = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSCloud1,xmlElement)) 
		errorLoadingTexture=true;
	
	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSCloud2 = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSCloud2,xmlElement)) 
		errorLoadingTexture=true;
	
	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSCloud3 = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSCloud3,xmlElement)) 
		errorLoadingTexture=true;
	
	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSFireBall = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSFireBall,xmlElement)) 
		errorLoadingTexture=true;
	
	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSProjectileEnemy = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSProjectileEnemy,xmlElement)) 
		errorLoadingTexture=true;
	
	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSEnemies = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSEnemies,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSExplosion = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSExplosion,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSShipExplosion = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSShipExplosion,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSDragonExplosion = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSDragonExplosion,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSLife = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSLife,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexStampede = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexStampede,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSBorderLife = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSBorderLife,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSMenu = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSMenu,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSD = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSD,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSOption = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSOption,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSBossBody = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSBossBody,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSSide = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSSide,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSEye = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSEye,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=xmlElement->NextSiblingElement();
	if(!xmlElement) return;
	int indexSMouth = 0;
	if(!errorLoadingTexture && !VIS.createSprite(&indexSMouth,xmlElement)) 
		errorLoadingTexture=true;

	xmlElement=handle.FirstChildElement().Child(2).FirstChildElement().Element();
	if(!errorLoadingTexture && !VIS.createFont(xmlElement))
		errorLoadingTexture=true;

	if(errorLoadingTexture)
	{
		VIS.Close();
		return;
	}

	
	//creation of the animations
	int indexADragonFlyUp;
	VIS.createAnimation(indexSDragon,&indexADragonFlyUp,1,9,120);
	int indexADragonFlyLeft;
	VIS.createAnimation(indexSDragon,&indexADragonFlyLeft,10,19,120);
	int indexADragonFlyRight;
	VIS.createAnimation(indexSDragon,&indexADragonFlyRight,20,29,120);
	int indexAImpactProjectile;
	VIS.createAnimation(indexSExplosion,&indexAImpactProjectile,1,7,40);
	int indexAExplosionShip;
	VIS.createAnimation(indexSShipExplosion,&indexAExplosionShip,1,7,40);
	int indexAExplosionDragon;
	VIS.createAnimation(indexSDragonExplosion,&indexAExplosionDragon,1,14,50);
	int indexABossEye;
	VIS.createAnimation(indexSEye,&indexABossEye,1,6,200);
	int indexABossMouth;
	VIS.createAnimation(indexSMouth,&indexABossMouth,1,4,200);

	//creation of entities
	WMODEL.createBackground(0,-528, indexSMap1, indexSMap2, 2,true);
	WMODEL.createCloud(0,-1024, indexSCloud1, 8,10000, true);
	WMODEL.createCloud(100,-1024, indexSCloud2, 8,5000, true);
	WMODEL.createCloud(50,-512, indexSCloud3, 8,5000, true);
	CEntityBoss::initialiseBoss(indexSBossBody,indexSSide,indexSEye,indexSMouth,indexABossEye,indexABossMouth);
	WMODEL.createPlayer(236,322,100,7,CEntityPlayer::eSpawn,50,true,indexADragonFlyUp,
							indexADragonFlyLeft, indexADragonFlyRight, 120);
	
	
	//creation of projectiles and templates
	int numberOfProjectile=50;
	PROJECTILEMANAGER.createAllProjectile(numberOfProjectile);
	PROJECTILEMANAGER.createProjectileTemplate(indexSFireBall,1,1,CVector2D(0,-10),10,eSidePlayer,28,0);
	PROJECTILEMANAGER.createProjectileTemplate(indexSFireBall,4,1,CVector2D(-5,-10),10,eSidePlayer,7,0);
	PROJECTILEMANAGER.createProjectileTemplate(indexSFireBall,7,1,CVector2D(5,-10),10,eSidePlayer,48,0);
	PROJECTILEMANAGER.createProjectileTemplate(indexSProjectileEnemy,1,1,CVector2D(0,10),
		10,eSideEnemy,15,VIS.getFrameHeight(indexSEnemies));
	PROJECTILEMANAGER.createProjectileTemplate(indexSProjectileEnemy,2,1,CVector2D(0,10),
		10,eSideEnemy,15,VIS.getFrameHeight(indexSEnemies));

	//creation of enemies templates
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,1,30,50,eProjectileLaser);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,2,30,50,eProjectileLaser);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,3,30,50,eProjectileLaser);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,4,30,50,eProjectileLaser);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,5,30,50,eProjectileLaser);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,1,30,50,eProjectileStar);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,2,30,50,eProjectileStar);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,3,30,50,eProjectileStar);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,4,30,50,eProjectileStar);
	ENEMYMANAGER.createEnemyTemplate(indexSEnemies,5,30,50,eProjectileStar);

	
	//creation of explosions and templates
	int numberOfExplosion=25;
	EXPLOSIONMANAGER.createAllExplosion(numberOfExplosion);
	EXPLOSIONMANAGER.createExplosionTemplate(indexAImpactProjectile,0,0);
	EXPLOSIONMANAGER.createExplosionTemplate(indexAExplosionShip,0,15);
	EXPLOSIONMANAGER.createExplosionTemplate(indexAExplosionDragon,-40,-10);

	//loading of sounds
	xmlElement=handle.FirstChildElement().Child(3).FirstChildElement().Element();
	string adressSound;
	while(xmlElement)
	{
		adressSound=xmlElement->GetText();
		SOUND.loadSound(adressSound);
		xmlElement=xmlElement->NextSiblingElement();
	}

	//creation of the user interface
	USERINT.Initialise(WMODEL.getIndexPlayer(), indexSLife,1, indexSBorderLife, indexSMenu, indexSD, indexSOption);

	HAPI_TColour* white=new HAPI_TColour(255,255,255);

	WMODEL.loadLevel(handle);
	WMODEL.setGameOver(false);

	int lastTick = HAPI->GetTime();
	int numberOfTick=20;
	bool intro=false;
	

	while(HAPI->Update() && !WMODEL.getExit())//we need the update here cause without the game doesn't stop if 
											  //we click on the cross	
	{
		int choice=0;
		//loop for the menu
		while(HAPI->Update() && !WMODEL.getExit() && choice!=eChoicePlay)
		{
			USERINT.getKeyboardData();
			
			if(!intro)
			{
				intro=USERINT.displayStudio(7000,indexStampede,white);
			}
			else if(intro && choice==0)
			{
				choice=USERINT.displayMenu();
			}
			if(choice==eChoiceExit)
			{
				WMODEL.setExit(true);
			}
			if(choice!=eChoiceExit && choice!=eChoicePlay && choice!=0)
			{
				choice=USERINT.displayMenuOption();
			}
		}
		
		WMODEL.resetLevel();

		//game loop
		while(HAPI->Update() && !WMODEL.getExit() && !WMODEL.getGameOver())
		{
			//catch the inputs
			USERINT.getKeyboardData();

			//tick:do the update every 50 ms
			if((int)HAPI->GetTime()>=lastTick+numberOfTick)
			{
				lastTick=HAPI->GetTime();
				WMODEL.update();
			}
			//draw the scene
			WMODEL.render();
			//HAPI->SetShowFPS(true,2,2);

			//display the UI
			USERINT.displayUserInterface();
		}
	}

	//deletion of all components
	delete white;
	VIS.Close();
	WMODEL.Close();
	PROJECTILEMANAGER.Close();
	EXPLOSIONMANAGER.Close();
	ENEMYMANAGER.Close();
	USERINT.Close();
	SOUND.Close();
	AI.Close();
	HAPI->Close();	
}